package com.xjn.updatetool.service.impl;

import com.xjn.updatetool.service.AppExtract;
import com.xjn.updatetool.util.FileNameUtil;
import com.xjn.updatetool.util.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileWriter;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

/**
 * @author lilin
 * @create 2020-07-30 14:33
 **/
@Service
public class AppExtractV1Impl implements AppExtract {
    @Value("${updatetool.extract.src.dir.java}")
    private String srcDirJava;
    @Value("${updatetool.extract.src.dir.classes}")
    private String srcDirClasses;
    @Value("${updatetool.extract.src.dir.resources}")
    private String srcDirResources;
    @Value("${updatetool.extract.src.dir.webapp}")
    private String srcDirWebapp;
    @Value("${updatetool.extract.log.dir}")
    private String dirLog;
    @Value("${updatetool.extract.exclude.ext}")
    private String excludeFileExt;
    @Value("${updatetool.extract.exclude.dir}")
    private String excludeDirs;
    @Value("${updatetool.extract.exclude.file}")
    private String excludeFiles;
    @Value("${updatetool.extract.dst.dir}")
    private String dirDst;


    @Override
    public void startExtract(Date afterDate) throws Exception {
        LocalDateTime now = LocalDateTime.now();
        StringBuffer log= new StringBuffer();

        log.append("升级时间：").append(now.toString()).append("\r\n");

        createClassesDir(log);
        createResourcesDir(log);
        createWebappDir(log);

        extractClassesFile(log,now,afterDate);
        extractResourceFile(log,now,afterDate);
        extractWebappFile(log,now,afterDate);

        File dstFile = new File(dirDst);
        FileUtils fileUtils = new FileUtils();
        List<File> fileList = fileUtils.visitAll(dstFile);
        fileUtils.removeNullFile(fileList);
        fileList = fileUtils.visitAll(dstFile);
        fileUtils.removeNullFile(fileList);
        fileList = fileUtils.visitAll(dstFile);
        fileUtils.removeNullFile(fileList);
        fileList = fileUtils.visitAll(dstFile);
        fileUtils.removeNullFile(fileList);
        fileList = fileUtils.visitAll(dstFile);
        fileUtils.removeNullFile(fileList);
        fileList = fileUtils.visitAll(dstFile);
        fileUtils.removeNullFile(fileList);
        fileList = fileUtils.visitAll(dstFile);
        fileUtils.removeNullFile(fileList);

        log.append("----结束-----");
        String logPath = FileNameUtil.createLogFilePath(dirLog,now,"抽取");
        FileWriter fileWriter = new FileWriter(logPath, true);
        fileWriter.write(log.toString());
        fileWriter.flush();
    }
    private void loopDir(File file,StringBuffer log,String src,String dst) throws Exception{
        File[] fs = file.listFiles();
        for(File f:fs){
            if(f.isDirectory()) {    //若是目录，则递归打印该目录下的文件
                updateDir(f,log,src,dst);
                loopDir(f,log,src,dst);
            }
        }
    }
    private void updateDir(File dir,StringBuffer log,String src,String dst) throws Exception {
        String dstPath = FileNameUtil.changeBaseDir(dir.getPath(),src,dst);
        File dstDir = new File(dstPath);
        if(!dstDir.exists()){//判断文件目录是否存在
            dstDir.mkdirs();
        }
    }
    private void createClassesDir(StringBuffer log) throws Exception{
        File file = new File(srcDirJava);        //获取其file对象
        String dst = dirDst + File.separator +"WEB-INF" + File.separator + "classes";
        loopDir(file,log,srcDirJava,dst);//补充文件夹
    }
    private void createResourcesDir(StringBuffer log) throws Exception{
        File file = new File(srcDirResources);        //获取其file对象
        String dst = dirDst + File.separator +"WEB-INF" + File.separator + "classes";
        loopDir(file,log,srcDirResources,dst);//补充文件夹
    }
    private void createWebappDir(StringBuffer log) throws Exception{
        File file = new File(srcDirWebapp);        //获取其file对象
        loopDir(file,log,srcDirWebapp,dirDst);//补充文件夹
    }
    private void extractClassesFile(StringBuffer log,LocalDateTime now,Date afterDate) throws Exception{
        File file = new File(srcDirJava);        //获取其file对象
        String dst = dirDst + File.separator +"WEB-INF" + File.separator + "classes";
        loopJavaFile(file,log,now,afterDate,dst);
    }
    private void loopJavaFile(File file,StringBuffer log,LocalDateTime now,Date afterDate,String dst) throws Exception{
        File[] fs = file.listFiles();
        for(File f:fs){
            if(f.isDirectory()) {    //若是目录，则递归打印该目录下的文件
                loopJavaFile(f,log,now,afterDate,dst);
            }
            if(f.isFile()) {        //若是文件，调用升级方法
                updateClassFile(f,log,now,srcDirJava,dst,srcDirClasses,afterDate);
            }
        }
    }
    public void updateClassFile(File file,StringBuffer log,LocalDateTime now,String dirJava,String dirDst,String dirClass,Date afterDate) throws Exception {
        Date fileDate = new Date(file.lastModified());
        if(fileDate.before(afterDate)){
            return;
        }
        if(isExcludeDir(file)){
            return;
        }
        if(isExcludeFile(file)){
            return;
        }
        if(isExcludeExt(file)){
            return;
        }

        String srcPath = FileNameUtil.changeBaseDir(file.getPath(),dirJava,dirClass);
        String dstPath = FileNameUtil.changeBaseDir(file.getPath(),dirJava,dirDst);
        if(srcPath.endsWith(".java")) {
            srcPath = srcPath.replace(".java", ".class");
            dstPath = dstPath.replace(".java", ".class");
        }
        File srcFile = new File(srcPath);
        File dstFile = new File(dstPath);
        FileCopyUtils.copy(srcFile,dstFile);
        System.out.println("抽取文件："+dstPath);
        log.append("抽取文件：").append(dstPath).append("\r\n");
    }
    boolean isExcludeExt(File file){
        if(StringUtils.isBlank(excludeFileExt)){
            return false;
        }
        String[] excludeArray = excludeFileExt.split(",");
        for(int i=0;i<excludeArray.length;i++){
            if(file.getName().endsWith(excludeArray[i])){
                return true;
            }
        }
        return false;
    }
    boolean isExcludeFile(File file){
        if(StringUtils.isBlank(excludeFiles)){
            return false;
        }
        String[] excludeArray = excludeFiles.split(",");
        for(int i=0;i<excludeArray.length;i++){
            if(file.getName().equalsIgnoreCase(excludeArray[i])){
                return true;
            }
        }
        return false;
    }
    boolean isExcludeDir(File file){
        if(StringUtils.isBlank(excludeDirs)){
            return false;
        }
        String[] excludeArray = excludeDirs.split(",");
        for(int i=0;i<excludeArray.length;i++){
            if(file.getPath().startsWith(excludeArray[i])){
                return true;
            }
        }
        return false;
    }
    private void extractResourceFile(StringBuffer log,LocalDateTime now,Date afterDate) throws Exception{
        File file = new File(srcDirResources);        //获取其file对象
        String dst = dirDst + File.separator +"WEB-INF" + File.separator + "classes";
        loopFile(file,log,now,afterDate,srcDirResources,dst);
    }
    private void extractWebappFile(StringBuffer log,LocalDateTime now,Date afterDate) throws Exception{
        File file = new File(srcDirWebapp);        //获取其file对象
        loopFile(file,log,now,afterDate,srcDirWebapp,dirDst);
    }
    private void loopFile(File file,StringBuffer log,LocalDateTime now,Date afterDate,String srcDir,String dstDir) throws Exception{
        File[] fs = file.listFiles();
        for(File f:fs){
            if(f.isDirectory()) {    //若是目录，则递归打印该目录下的文件
                loopFile(f,log,now,afterDate,srcDir,dstDir);
            }
            if(f.isFile()) {        //若是文件，调用升级方法
                updateFile(f,log,now,srcDir,dstDir,afterDate);
            }
        }
    }
    public void updateFile(File file,StringBuffer log,LocalDateTime now,String srcDir,String dstDir,Date afterDate) throws Exception {
        Date fileDate = new Date(file.lastModified());
        if(fileDate.before(afterDate)){
            return;
        }
        if(isExcludeDir(file)){
            return;
        }
        if(isExcludeFile(file)){
            return;
        }
        if(isExcludeExt(file)){
            return;
        }
        String dstPath = FileNameUtil.changeBaseDir(file.getPath(),srcDir,dstDir);
        File dstFile = new File(dstPath);
        FileCopyUtils.copy(file,dstFile);
        System.out.println("抽取文件："+file.getPath());
        log.append("抽取文件：").append(file.getPath()).append("\r\n");
    }

}
